/**
 * 
 */
package dictionary;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;


import java.util.Set;

import dictionary.PallierEncypt;
import dictionary.Response;

/**
 * @author nicholas addae
 */
public class Authenticated_Dictionary {
	
	/**
	 * Dictionary for storing the data and tag values
	 */
	private static HashMap<Integer, BigInteger> dict=new HashMap();
	private static Integer dummyMsg;
	private static BigInteger n;
	/**
	 * Class used for encryption and decryption
	 */
	private static PallierEncypt pall;
	
	/**
	 * Constructor for the class
	 */
	public Authenticated_Dictionary()
	{
		pall = new PallierEncypt();
		n = pall.n;
		dummyMsg = 1;
		dict.put(dummyMsg,pall.Encryption(BigInteger.valueOf(dummyMsg)));
	}
	
	/** This function will create the dictionary from the given array
	 * @param values the array of integers used to create the dictionary
	 */
	public  void createDictionary(Integer [] values)
	{
		if (values.length==0 ||values==null) //check if array is empty 		
			{
			System.out.println("The input array is empty");
			return;
		}
		 
		for (int i=0;i<values.length;i++)
		{
			BigInteger bi = BigInteger.valueOf(values[i].intValue());
			BigInteger ki = pall.Encryption(bi);
			if(!dict.containsKey(values[i]))
			{
			dict.put(values[i],ki);
			}
			 
		}
	}
	public Response queryResponse(Integer request)
	{
		if(!dict.containsKey(request))
		{
			System.out.println("The requested item " + request + " is not present");
			return null;
		}
		Integer dummy = Authenticated_Dictionary.dummyMsg;
		BigInteger convertedRequest = BigInteger.valueOf(request);
		BigInteger convertedDummy = BigInteger.valueOf(dummy);
		BigInteger encryptedMessage = dict.get(request);
		BigInteger encryptedResponse = (pall.Encryption(convertedRequest).multiply(pall.Encryption(convertedDummy))).mod(n.multiply(n));//made a change here instead of n
		Response answer = new Response(encryptedMessage, encryptedResponse, n, dummyMsg, Authenticated_Dictionary.pall);
		return answer;
	}
	public void insertElement(Integer x) 
	{
		
		if(dict.containsKey(x))
		{
			System.out.println("Element to be inserted  already exists. Insertion Failed\n");
			return;
		} 
		else 
		{
			BigInteger newVal=pall.Encryption(BigInteger.valueOf(x));
			dict.put(x, newVal);
			System.out.println("New data , tag pair inserted is \n" + x + " ," + newVal + "\n");
		}

	}
	/**
	 * Prints the key-value pair in a dictionary
	 */
	public  void PrintElements()
	{
		Set<Integer> keyset=dict.keySet();	
		Iterator<Integer> keySetIterator=keyset.iterator();
		System.out.println("The current status of the dictionary : \n\nData\tTags");
		while(keySetIterator.hasNext())
		{
			Integer key = keySetIterator.next();
			System.out.println( key +"\t"+dict.get(key));
		}
		System.out.println();
	}
	/**This function deletes an element k and its associated value from the dictionary 
	 * @param k key of element  to be deleted
	 */
	public void deleteElemenk(Integer k)
	{
		if(!dict.containsKey(k))
		{
			System.out.println( "No element : " + k + "exists in the dictionary. Deletion failed\n");
		}
		System.out.println( "Deleting element : " + k + "\n");
		dict.remove(k);
	}
	/**Carries out an update operation, modifying old value to new value
	 * @param oldval the value to be replaced
	 * @param newval the value to be replaced with
	 */
	public void Update(Integer oldval,Integer newval)
	{
		if(!dict.containsKey(oldval))
		{
			System.out.println("Value to be updated does not exist in dictionary. Updation Failed\n");
			return;
		}
		else
		{
			System.out.println( "Updating element " + oldval + " to " + newval + "\n");
			dict.remove(oldval);
			BigInteger Value = pall.Encryption(BigInteger.valueOf(newval));
			dict.put(newval,Value);
		}
	}
}